#include "../StdInc.h"
namespace GSTrader
{
	namespace Indicator
	{
		EMA::EMA()
		{
			m_strIndicatorName = "EMA";
			m_nLength = 0;
			m_nBarType = bdtClose;
		}

		EMA::~EMA()
		{

		}

		CIndicator* EMA::CreateInstance()
		{
			return new EMA;
		}

		void EMA::SetParam(int nLength, int nBarType)
		{
			m_nLength = nLength;
			m_nBarType = nBarType;
			RefreshData();
		}

		void EMA::SetParam(double* pdParam)
		{
			if (pdParam == NULL)
			{
				//assert(false);
				return;
			}

			m_nLength = (int)pdParam[0];
			m_nBarType = (int)pdParam[1];

			RefreshData();
		}

		void EMA::RefreshData()
		{
			if (m_pInput == NULL || m_nLength <= 0 || m_pInput->m_nStartIndex < 0)
			{
				m_pResult->m_pDataSeries->m_nStartIndex = -1;
				return;
			}
				

			int nCount = m_pInput->GetCount();

			int nStartIndex = m_pInput->m_nStartIndex;
			m_pResult->m_pDataSeries->SetSize(nCount, nStartIndex);

			m_bCalc = true;
		}

		double EMA::Calculate(int nIndex)
		{
			if (m_pInput == NULL || m_pInput->m_nStartIndex < 0 || m_nLength <= 0)
				return 0;

			int nCount = m_pInput->GetCount();
			if (nIndex < m_pInput->m_nStartIndex || nIndex >= nCount)
			{
				if (nIndex >= 0 && nIndex < m_pInput->m_nStartIndex)
				{
					m_pResult->SetValue(nIndex, 0);
				}
				return 0;
			}
				
			double dValue;
			if (nIndex == m_pInput->m_nStartIndex)
			{
				dValue = m_pInput->GetValue(m_pInput->m_nStartIndex, m_nBarType);
					m_pResult->SetValue(nIndex, dValue);
			}
			else
			{
				double dPreResult = m_pResult->GetValue(nIndex - 1);
				double dCurInput = m_pInput->GetValue(nIndex, m_nBarType);
				dValue = (2 * dCurInput + (m_nLength - 1) * dPreResult) / (m_nLength + 1);
				m_pResult->SetValue(nIndex, dValue);
			}

			return dValue;
		}
	}
}